package com.jzo2o.trade.service.impl;

import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.jzo2o.api.trade.dto.response.ExecutionResultResDTO;
import com.jzo2o.api.trade.enums.PayChannelEnum;
import com.jzo2o.common.constants.MqConstants;
import com.jzo2o.common.expcetions.CommonException;
import com.jzo2o.trade.enums.RefundStatusEnum;
import com.jzo2o.trade.model.domain.RefundRecord;
import com.jzo2o.trade.model.domain.Trading;
import com.jzo2o.trade.service.IRefundRecordService;
import com.jzo2o.trade.service.IRefundService;
import com.jzo2o.trade.service.ITradingService;
import com.jzo2o.trade.service.IWxRefundService;
import com.wechat.pay.java.service.refund.model.RefundNotification;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.HashMap;

@Service
@Slf4j
public class RefundServiceImpl implements IRefundService {

    @Autowired
    private IWxRefundService wxRefundService;
    @Autowired
    private ITradingService tradingService;
    @Autowired
    private IRefundRecordService refundRecordService;
    @Resource
    private RabbitTemplate rabbitTemplate;

    /**
     * 退款
     */
    @Override
    public ExecutionResultResDTO refund(Long tradingOrderNo, BigDecimal refundAmount) {
        //1 查询交易单
        Trading trading = tradingService.getOne(Wrappers.<Trading>lambdaQuery().eq(Trading::getTradingOrderNo, tradingOrderNo));
        if (trading == null) {
            log.error("交易单不存在");
            return null;
        }
        //2 创建退款单
        RefundRecord refundRecord = new RefundRecord();
        refundRecord.setTradingOrderNo(trading.getTradingOrderNo());
        refundRecord.setProductOrderNo(trading.getProductOrderNo());
        refundRecord.setRefundNo(generateRefundNo(trading.getProductOrderNo()));
        refundRecord.setTradingChannel(trading.getTradingChannel());
        refundRecord.setRefundStatus(RefundStatusEnum.SENDING.getCode());
        refundRecord.setRefundAmount(refundAmount);
        refundRecord.setTotal(trading.getTradingAmount());
        refundRecordService.save(refundRecord);
        //根据支付方式选择不同的退款服务
        if (PayChannelEnum.WECHAT_PAY.getValue().equals(trading.getTradingChannel())) {
            return wxRefundService.refund(refundRecord);
        }
        //TODo 支付宝
        return null;
    }

    /**
     * 退款成功回调操作
     *
     * @param transaction
     */
    @Override
    public void refundSuccess(RefundNotification transaction) {
        RefundRecord refundRecord = refundRecordService.getOne(Wrappers.<RefundRecord>lambdaQuery().eq(RefundRecord::getRefundNo, transaction.getOutRefundNo()));
        if (refundRecord == null) {
            throw new CommonException("退款单不存在");
        }
        //更新交易单信息
        refundRecord.setRefundId(transaction.getRefundId());
        refundRecord.setRefundStatus(RefundStatusEnum.SUCCESS.getCode());
        refundRecordService.updateById(refundRecord);
        //mq 通知订单服务 退款成功
        HashMap<String, Object> refundMap = new HashMap<>();
        refundMap.put("refundId", transaction.getRefundId());
        refundMap.put("refundNo", transaction.getOutRefundNo());
        refundMap.put("tradingNo", transaction.getOutTradeNo());
        rabbitTemplate.convertAndSend(MqConstants.Exchanges.TRADE, MqConstants.RoutingKeys.REFUND, JSONUtil.toJsonStr(refundMap));
    }

    /**
     * 生成退款单号
     */
    private Long generateRefundNo(Long p) {
        return Long.valueOf("00" + p);
    }
}
